package com.msb.dongbao.portal.web.code;

import sun.font.FontDesignMetrics;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * @author: mayu
 * @date: 2021年05月28日 8:53
 */
public class ValidCodeGenerator {
    private static final char[] CODESEQ = new char[]{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9'};
    private static final Color[] COLORS;

    public static Map<String, Object> generateCodeAndPic(int width, int height, int codeCount) {
        if (codeCount <= 6 && codeCount >= 4) {
            if (width > 0 && height > 0) {
                double value = countHeightRatio(width, height, codeCount);
                BufferedImage buffImg = new BufferedImage(width, height, 1);
                Graphics gd = buffImg.getGraphics();
                Random random = new Random();
                gd.fillRect(0, 0, width, height);
                int fontHeight = (int) ((double) height * value);
                if (height / 100 > 0) {
                    fontHeight += random.nextInt(height / 100);
                }

                Font font = new Font("Fixedsys", 1, fontHeight);
                gd.setFont(font);
                gd.setColor(Color.BLACK);
                gd.drawRect(0, 0, width - 1, height - 1);
                FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
                int yy = (height - metrics.getHeight()) / 2 + metrics.getAscent();
                StringBuffer randomCode = new StringBuffer();

                for (int i = 0; i < codeCount; ++i) {
                    int xx = width / codeCount;
                    if (width / 100 > 0) {
                        xx -= random.nextInt(width / 100);
                    }

                    String code = String.valueOf(CODESEQ[random.nextInt(CODESEQ.length)]);
                    int red = random.nextInt(195);
                    int green = random.nextInt(195);
                    int blue = random.nextInt(195);
                    gd.setColor(new Color(red, green, blue));
                    gd.drawString(code, i * xx, yy);
                    randomCode.append(code);
                }

                disturbLine(width, height, gd);
                Map<String, Object> map = new HashMap();
                map.put("code", randomCode.toString());
                ByteArrayOutputStream tmp = new ByteArrayOutputStream();

                try {
                    ImageIO.write(buffImg, "jpg", tmp);
                    tmp.close();
                } catch (IOException var19) {
                    var19.printStackTrace();
                    return null;
                }

                map.put("codePic", tmp.toByteArray());
                return map;
            } else {
                throw new IllegalArgumentException("参数错误,图片的高和宽必须是正数");
            }
        } else {
            throw new IllegalArgumentException("参数错误,只能生成4至6位验证码");
        }
    }

    private static void disturbLine(int width, int height, Graphics gd) {
        Random random = new Random();
        int lineNum = width * height / 100;

        for (int i = 0; i < lineNum; ++i) {
            gd.setColor(COLORS[random.nextInt(COLORS.length)]);
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(20);
            int yl = random.nextInt(20);
            gd.drawLine(x, y, x + xl, y + yl);
        }

    }

    private static double countHeightRatio(int width, int height, int codeCount) {
        double value = 0.75D;
        BigDecimal whRatio = (new BigDecimal(width)).divide(new BigDecimal(height), 2, 4);
        if (whRatio.intValue() < 3 && codeCount > 4) {
            BigDecimal divideNum = (new BigDecimal(codeCount)).multiply(new BigDecimal(height)).divide(new BigDecimal(width), 2, 4);
            BigDecimal ratio = (new BigDecimal(1.5D)).divide(divideNum, 2, 4);
            value = ratio.doubleValue();
        }

        return value;
    }

    static {
        COLORS = new Color[]{Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.gray, Color.GREEN, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.RED, Color.WHITE, Color.YELLOW};
    }
}
